/*
 * DevicesLed.c
 *
 *      Author: Honrun
 */

#include "gd32f10x.h"
#include "DevicesSoftTimer.h"
#include "DevicesLed.h"


static LedInfoType st_typeLedInfo;

/* 周期调用计数（调用频率为10k） */
volatile static uint32_t st_uiLedTickCnt = 0;

SoftTimerTypeDef g_typeSoftTimerLedHanle = {0};


void vSoftTimerLedCallbackFunction(void *pvHandle)
{
    (void)pvHandle;

    vLedMachine();
}

void vLedInit(void)
{
    /* enable the LED GPIO clock */
    rcu_periph_clock_enable(RCU_GPIOE);

    /* configure LED GPIO pin */
    gpio_init(LED_WHITE_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, LED_WHITE_Pin);
    gpio_init(LED_YELLOW_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, LED_YELLOW_Pin);
    gpio_init(LED_GREEN_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, LED_GREEN_Pin);

    vLedOpen(LED_ALL);


    st_typeLedInfo.white.periph = LED_WHITE_GPIO_Port;
    st_typeLedInfo.white.pin = LED_WHITE_Pin;

    st_typeLedInfo.yellow.periph = LED_YELLOW_GPIO_Port;
    st_typeLedInfo.yellow.pin = LED_YELLOW_Pin;

    st_typeLedInfo.green.periph = LED_GREEN_GPIO_Port;
    st_typeLedInfo.green.pin = LED_GREEN_Pin;


    /* 软件定时器周期调用 */
    cSoftTimerCreateMs(&g_typeSoftTimerLedHanle, 100, softTimerOpen | softTimerCircular, vSoftTimerLedCallbackFunction);

    vLedSetStatus(LED_ALL, LED_FLASH_SLOW, 10);
}

void vLedOpen(uint16_t usChannel)
{
    if(usChannel & LED_WHITE)
        gpio_bit_set(LED_WHITE_GPIO_Port, LED_WHITE_Pin);
    if(usChannel & LED_YELLOW)
        gpio_bit_set(LED_YELLOW_GPIO_Port, LED_YELLOW_Pin);
    if(usChannel & LED_GREEN)
        gpio_bit_set(LED_GREEN_GPIO_Port, LED_GREEN_Pin);
}

void vLedClose(uint16_t usChannel)
{
    if(usChannel & LED_WHITE)
        gpio_bit_reset(LED_WHITE_GPIO_Port, LED_WHITE_Pin);
    if(usChannel & LED_YELLOW)
        gpio_bit_reset(LED_YELLOW_GPIO_Port, LED_YELLOW_Pin);
    if(usChannel & LED_GREEN)
        gpio_bit_reset(LED_GREEN_GPIO_Port, LED_GREEN_Pin);
}

void vLedRevesal(uint16_t usChannel)
{
    if(usChannel & LED_WHITE)
        gpio_bit_write(LED_WHITE_GPIO_Port, LED_WHITE_Pin,   (gpio_output_bit_get(LED_WHITE_GPIO_Port, LED_WHITE_Pin) != RESET) ? RESET : SET);
    if(usChannel & LED_YELLOW)
        gpio_bit_write(LED_YELLOW_GPIO_Port, LED_YELLOW_Pin, (gpio_output_bit_get(LED_YELLOW_GPIO_Port, LED_YELLOW_Pin) != RESET) ? RESET : SET);
    if(usChannel & LED_GREEN)
        gpio_bit_write(LED_GREEN_GPIO_Port, LED_GREEN_Pin,   (gpio_output_bit_get(LED_GREEN_GPIO_Port, LED_GREEN_Pin) != RESET) ? RESET : SET);
}

/*
 * Return:      void
 * Parameters:  usChannel: LED通道; usChannel: 状态; usChannel: 闪烁次数/或者占空比;
 * Description: 设置LED状态
 */
void vLedSetStatus(uint16_t usChannel, LedStateEnum enumStatus, uint8_t ucFlashCnt_or_Duty)
{
    if(usChannel & LED_YELLOW)
    {
        st_typeLedInfo.yellow.state = enumStatus;
        st_typeLedInfo.yellow.flashCnt = ucFlashCnt_or_Duty * 2 + 1;
        st_typeLedInfo.yellow.duty = ucFlashCnt_or_Duty % 101;
    }
    if(usChannel & LED_WHITE)
    {
        st_typeLedInfo.white.state = enumStatus;
        st_typeLedInfo.white.flashCnt = ucFlashCnt_or_Duty * 2 + 1;
        st_typeLedInfo.white.duty = ucFlashCnt_or_Duty % 101;
    }
    if(usChannel & LED_GREEN)
    {
        st_typeLedInfo.green.state = enumStatus;
        st_typeLedInfo.green.flashCnt = ucFlashCnt_or_Duty * 2 + 1;
        st_typeLedInfo.green.duty = ucFlashCnt_or_Duty % 101;
    }
}

/*
 * Return:      void
 * Parameters:  *ptypeLed: LED信息结构体
 * Description: LED状态刷新
 */
void vLedStateMachine(LedType *ptypeLed)
{
    switch(ptypeLed->state)
    {
        /* 关闭 */
        case LED_DISABLE:
            GPIO_BC(ptypeLed->periph) = ptypeLed->pin;
            ptypeLed->state = LED_IDLE;
            break;

        /* 常亮 */
        case LED_ENABLE:
            GPIO_BOP(ptypeLed->periph) = ptypeLed->pin;
            ptypeLed->state = LED_IDLE;
            break;

        /* 呼吸 */
        case LED_BREATHE: break;

        /* 固定占空比 */
        case LED_DUTY: break;

        /* 快闪/快闪后关闭/快闪后常亮 */
        case LED_FLASH_SLOW:
        case LED_FLASH_SLOW_DISABLE_CNT:
        case LED_FLASH_SLOW_ENABLE_CNT:
            if((st_uiLedTickCnt % 10) == 0)
            {
                gpio_bit_write(ptypeLed->periph, ptypeLed->pin, (gpio_output_bit_get(ptypeLed->periph, ptypeLed->pin) != RESET) ? RESET : SET);

                if((ptypeLed->state != LED_FLASH_SLOW) && ((ptypeLed->flashCnt--) <= 0))
                {
                    ptypeLed->state = (ptypeLed->state == LED_FLASH_SLOW_ENABLE_CNT) ? LED_ENABLE : LED_DISABLE;
                }
            }
            break;

        /* 慢闪/慢闪后关闭/慢闪后常亮 */
        case LED_FLASH_FAST:
        case LED_FLASH_FAST_DISABLE_CNT:
        case LED_FLASH_FAST_ENABLE_CNT:
            if((st_uiLedTickCnt % 5) == 0)
            {
                gpio_bit_write(ptypeLed->periph, ptypeLed->pin, (gpio_output_bit_get(ptypeLed->periph, ptypeLed->pin) != RESET) ? RESET : SET);

                if((ptypeLed->state != LED_FLASH_FAST) && ((ptypeLed->flashCnt--) <= 0))
                {
                    ptypeLed->state = (ptypeLed->state == LED_FLASH_FAST_ENABLE_CNT) ? LED_ENABLE : LED_DISABLE;
                }
            }
            break;

        default : break;
    }
}

/*
 * Return:      void
 * Parameters:  void
 * Description: LED心跳计数 + 呼吸状态机
 */
static void vLedIncTick(void)
{
    /* 所有LED使用同一个状态机变量，以方便实现一致的闪烁步调 */
    ++st_uiLedTickCnt;
}

void vLedMachine(void)
{
    vLedIncTick();

    vLedStateMachine(&st_typeLedInfo.white);

    vLedStateMachine(&st_typeLedInfo.yellow);

    vLedStateMachine(&st_typeLedInfo.green);
}

LedInfoType *ptypeLedGetInfo(void)
{
    return &st_typeLedInfo;
}
